
#ifndef _TTG_DEVICES_DEVICE_MAP_
#define _TTG_DEVICES_DEVICE_MAP_
#include "Common/Definitions.h"

#include <vector>
#include "Common/Structures.h"

#include "DeviceMap.h"
#include "ApiMap.h"

namespace ttg_internal
{
	namespace devices
	{
		//Enumerator for map with logical devices.
		template <class T>
		class LogicalDeviceMapEnumerator :public ttg::structures::Enumerator<T>
		{
			private:
				ttg::devices::DeviceMap<ttg::devices::ApiMap<T> > *values;
				ttg::structures::Enumerator<ttg::devices::ApiMap<T> > *device_en;
				ttg::structures::Enumerator<T> *api_en;
				//Creates reseted LogicalDeviceMapEnumerator.
			public:
				inline LogicalDeviceMapEnumerator(
					ttg::devices::DeviceMap<ttg::devices::ApiMap<T> > *values)
				{
					this->values = values;
					device_en = values->getEnumerator();
					api_en = NULL;
				}
				//Enumerator<T> member.
				//Moves to next element. If there aren't any, returns false.
				virtual bool moveNext()
				{
					if (api_en == NULL)
					{
						if (device_en->moveNext())
						{
							api_en = device_en->current().getEnumerator();
							return moveNext();
						}
						else
							return false;
					}
					else
					{
						if (api_en->moveNext())
							return true;
						else
						{
							SAFE_DELETE(api_en);
							return moveNext();
						}
					}
				}
				//Enumerator<T> member. Returns current element.
				virtual T &current()
				{ return api_en->current(); }
				//Enumerator<T> member. Resets enumerator to initial state.
				virtual void reset()
				{ SAFE_DELETE(api_en); device_en->reset(); }
				//Releases created enumerators.
				virtual ~LogicalDeviceMapEnumerator()
				{ SAFE_DELETE(device_en); }
		};
	}
}

namespace ttg
{
	namespace devices
	{
		//Maps device+API bundles to values.
		template <class T>
		class LogicalDeviceMap :public ttg::structures::EnumerableCollection<T>
		{
			private:
				ttg::devices::DeviceMap<ttg::devices::ApiMap<T> > values;
			public:
				//EnumerableCollection<T> member. Returns enumerator for current collection.
				virtual ttg::structures::Enumerator<T> *getEnumerator()
				{ return new ttg_internal::devices::LogicalDeviceMapEnumerator<T>(&values); }
				//Returns requred value (and, optionally, registers device)
				inline T &operator[](const LogicalDevice type)
				{ return values[type.getDevice()][type.getAPI()]; }
				//Returns true, if value was assigned to required device.
				inline bool isContained(DeviceID device)
				{ return values.isContained(device); }
				//Returns true, if value was assigned to required device + api.
				inline bool isContained(LogicalDevice device)
				{
					if (values.isContained(device.getDevice()))
						return values[device.getDevice()].isContained(device.getAPI());
					else
						return false;
				}
				//Returns all devices, which values was assigned to.
				inline std::vector<DeviceID> getDevices()
				{ return values.getIndices(); }
				//Returns all API for device, that value was assigned to.
				inline std::vector<ApiID> getAPI(DeviceID device)
				{ return values[device].getIndices(); }
				//Clears all records.
				inline void clear()
				{ values.clear(); }
		};
	}
}

#endif
